/*
 * Gedigarr - Falling block game.
 * Copyright (C) 2010  BoredCorp
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
package gedigarr.graphics;

import gedigarr.game.GameConstants;
import gedigarr.game.GameState;
import gedigarr.grid.GameGrid;
import gedigarr.grid.GridInterface;
import gedigarr.grid.MenuGrid;
import gedigarr.grid.ScoreGrid;
import gedigarr.grid.ScoreInputGrid;
import gedigarr.objects.Cell;
import gedigarr.objects.Tetromino;
import gedigarr.resources.GameResource;
import gedigarr.resources.ResourceManager;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Rectangle;

/**
 * Handles graphics of game. Includes buffer strategies and GUI designs.
 * <p>
 * Uses an instance to GameState to retrieve game data.
 * @author JC
 */
public class GameGraphics extends Canvas {

  GameState state;
  Font fontScore;
  Font fontLabel;
  GradientPaint bgPaint = new GradientPaint( 0, 0, Color.GRAY, 35, 100, Color.DARK_GRAY, true );
  final String TOP_STRING = "TOP";
  final String SCORE_STRING = "SCORE";
  final String LEVEL_STRING = "LEVEL";
  final String CLEARED_STRING = "CLEARED";
  final String TIME_STRING = "TIME";

  public GameGraphics( GameState state ) {
    this.state = state;
    GameResource<Font> gr = ResourceManager.getInstance().loadFont( "fonts/pooto2.ttf", ResourceManager.LOC_JAR );
    this.fontLabel = gr.getResource().deriveFont( 16.0f );
    this.fontScore = new Font( "Courier New", Font.BOLD, 14 );
    setIgnoreRepaint( true );
  }

  public void initialise() {
    createBufferStrategy( 2 );
  }

  private void paintCellGrid( Graphics2D g, GridInterface<? extends Cell> grid,
          int cX, int cY, Color colour, boolean showVisible, boolean showSolid ) {
    int rows = grid.getRows();
    int cols = grid.getColumns();
    int cWidth = GameConstants.CELL_WIDTH;

    for ( int r = 0; r < rows; r++ ) {
      for ( int c = 0; c < cols; c++ ) {
        Cell cell = grid.get( c, r );
        if ( ( cell.isVisible() && showVisible ) || ( cell.isSolid() && showSolid ) ) {
          cell.draw( g, c * cWidth + c + cX, r * cWidth + r + cY, cWidth, cWidth, colour, true );
        } else {
          cell.draw( g, c * cWidth + c + cX, r * cWidth + r + cY, cWidth, cWidth, Color.BLACK, false );
        }
      }
    }


  }

  public void paintNext( Graphics2D g, Tetromino tetro, int x, int y, int w, int h ) {
    Cell cell;
    //center-corrected location values
    int xC, yC;
    //    to center: (width - totalCellWidth) /2
    int tHeight = tetro.getHeight( 0 );
    int tPxHeight = tHeight * 20 + tHeight - 1;
    int tWidth = tetro.getWidth( 0 );
    int tPxWidth = tWidth * 20 + tWidth - 1;

    for ( int r = 0; r < tHeight; r++ ) {
      for ( int c = 0; c < tWidth; c++ ) {
        cell = tetro.get( 0, c, r );
        xC = x + ( w - tPxWidth ) / 2;
        yC = y + ( h - tPxHeight ) / 2;
        if ( cell.isVisible() ) {
          cell.draw( g, xC + ( c * 20 + c ), yC + ( r * 20 + r ), 20, 20 );
        }
      }
    }
  }

  public void paint() {
    Graphics2D g = (Graphics2D) getBufferStrategy().getDrawGraphics();
    GameGrid grid = this.state.getGameGrid();
    MenuGrid mGrid = this.state.getMenuGrid();
    ScoreGrid sGrid = this.state.getScoreGrid();
    ScoreInputGrid iGrid = this.state.getInputGrid();
    Tetromino next = grid.getNextTetro();

    g.clearRect( 0, 0, getWidth(), getHeight() );
    g.setPaint( bgPaint );
    g.fill( new Rectangle( 0, 0, getWidth(), getHeight() ) );

    g.setColor( Color.BLACK );
    g.fill( new Rectangle( 185, 15, 100, 100 ) );

    switch ( state.getState() ) {
      case GameState.STATE_RUNNING:
        paintCellGrid( g, grid, 0, 0, null, true, true );
        paintNext( g, next, 185, 15, 100, 100 );
        //paintCellGrid( g, next, 193, 21, null );
        g.setColor( Color.BLACK );
        g.setFont( fontLabel.deriveFont( 20.0f ) );
        g.drawString( "P to Pause", 205, 370 );
        break;
      case GameState.STATE_PAUSED:
        paintCellGrid( g, grid, 0, 0, Color.GRAY, false, true );
        paintNext( g, next, 185, 15, 100, 100 );
        g.setColor( Color.BLACK );
        g.setFont( fontLabel.deriveFont( 20.0f ) );
        g.drawString( "P to Resume", 200, 370 );
        break;
      case GameState.STATE_GAMEOVER:
        paintCellGrid( g, grid, 0, 0, Color.GRAY, true, true );
        g.setColor( Color.BLACK );
        g.setFont( fontLabel.deriveFont( 20.0f ) );
        g.drawString( "Space to Menu", 180, 370 );
        break;
      case GameState.STATE_MENU:
        paintCellGrid( g, mGrid, 0, 0, null, true, true );
        g.setColor( Color.BLACK );
        g.setFont( fontLabel.deriveFont( 20.0f ) );
        g.drawString( "Space to Select", 180, 370 );
        break;
      case GameState.STATE_SCORES:
        paintCellGrid( g, sGrid, 0, 0, null, true, true );
        g.setColor( Color.BLACK );
        g.setFont( fontLabel.deriveFont( 20.0f ) );
        g.drawString( "Space to Menu", 180, 370 );
        break;
      case GameState.STATE_SCORE_INPUT:
        paintCellGrid( g, iGrid, 0, 0, null, true, true );
        g.setColor( Color.BLACK );
        g.setFont( fontLabel.deriveFont( 20.0f ) );
        g.drawString( "Space to Select", 180, 370 );
        break;
    }

    /*
    for ( int y = 0; y < next.getRows(); y++ ) {
    for ( int x = 0; x < next.getColumns(); x++ ) {
    Cell c = next.get( x, y );
    c.draw( g, x * cWidth + x, y * cWidth + y, cWidth, cWidth, c.getBGColour() );
    }
    }
     */

    //DRAW SCORE
    g.setFont( fontLabel );

    g.setColor( Color.BLACK );

    g.drawString( TOP_STRING, 200, 140 );
    g.drawString( SCORE_STRING, 200, 180 );
    g.drawString( LEVEL_STRING, 200, 220 );
    g.drawString( CLEARED_STRING, 200, 260 );
    g.drawString( TIME_STRING, 200, 300 );
    g.setFont( fontScore );
    g.drawString( Long.toString( state.getHighScore() ), 200, 155 );
    g.drawString( Long.toString( state.getScore() ), 200, 195 );
    g.drawString( Integer.toString( state.getLevel() ), 200, 235 );
    g.drawString( Integer.toString( state.getCleared() ), 200, 275 );
    g.drawString( Long.toString( state.getTimeMillis() / 1000 ), 200, 315 );

    g.dispose();

    this.getBufferStrategy().show();
  }
}
